<!DOCTYPE html>
<!--[if IE 8]><html class="no-js lt-ie9" lang="en" > <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="en" > <!--<![endif]-->
<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  
  
  
  <link rel="shortcut icon" href="img/favicon.ico">
  <title>Lua脚本 - Minetest Modding Books(中文版)</title>
  <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Lato:400,700|Roboto+Slab:400,700|Inconsolata:400,700" />

  <link rel="stylesheet" href="css/theme.css" />
  <link rel="stylesheet" href="css/theme_extra.css" />
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.5.0/styles/github.min.css" />
  
  <script>
    // Current page data
    var mkdocs_page_name = "Lua\u811a\u672c";
    var mkdocs_page_input_path = "4.Lua\u811a\u672c.md";
    var mkdocs_page_url = null;
  </script>
  
  <script src="js/jquery-2.1.1.min.js" defer></script>
  <script src="js/modernizr-2.8.3.min.js" defer></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.5.0/highlight.min.js"></script>
  <script>hljs.initHighlightingOnLoad();</script> 
</head>

<body class="wy-body-for-nav" role="document">

  <div class="wy-grid-for-nav">

    
    <nav data-toggle="wy-nav-shift" class="wy-nav-side stickynav">
    <div class="wy-side-scroll">
      <div class="wy-side-nav-search">
        <a href="index.html" class="icon icon-home"> Minetest Modding Books(中文版)</a>
        <div role="search">
  <form id ="rtd-search-form" class="wy-form" action="./search.html" method="get">
      <input type="text" name="q" placeholder="Search docs" title="Type search term here" />
  </form>
</div>
      </div>

      <div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="main navigation">
                <ul>
                    <li class="toctree-l1"><a class="reference internal" href="index.html">首页</a>
                    </li>
                </ul>
                <ul>
                    <li class="toctree-l1"><a class="reference internal" href="1.%E8%AF%91%E8%80%85%E5%BA%8F.html">译者序</a>
                    </li>
                </ul>
                <ul>
                    <li class="toctree-l1"><a class="reference internal" href="2.%E5%89%8D%E8%A8%80.html">前言</a>
                    </li>
                </ul>
                <ul>
                    <li class="toctree-l1"><a class="reference internal" href="3.%E5%85%A5%E9%97%A8.html">入门</a>
                    </li>
                </ul>
                <ul class="current">
                    <li class="toctree-l1 current"><a class="reference internal current" href="4.Lua%E8%84%9A%E6%9C%AC.html">Lua脚本</a>
    <ul class="current">
    <li class="toctree-l2"><a class="reference internal" href="#_1">代码编辑器</a>
    </li>
    <li class="toctree-l2"><a class="reference internal" href="#lua_1">用Lua写代码</a>
        <ul>
    <li class="toctree-l3"><a class="reference internal" href="#_2">程序流</a>
    </li>
    <li class="toctree-l3"><a class="reference internal" href="#_3">变量类型</a>
    </li>
    <li class="toctree-l3"><a class="reference internal" href="#_4">算术运算符</a>
    </li>
    <li class="toctree-l3"><a class="reference internal" href="#_5">判断</a>
    </li>
    <li class="toctree-l3"><a class="reference internal" href="#_6">逻辑运算符</a>
    </li>
        </ul>
    </li>
    <li class="toctree-l2"><a class="reference internal" href="#_7">编程</a>
    </li>
    <li class="toctree-l2"><a class="reference internal" href="#_8">本地和全局范围</a>
        <ul>
    <li class="toctree-l3"><a class="reference internal" href="#_9">尽量使用本地变量</a>
    </li>
        </ul>
    </li>
    <li class="toctree-l2"><a class="reference internal" href="#lua_2">包含其他Lua脚本</a>
    </li>
    </ul>
                    </li>
                </ul>
                <ul>
                    <li class="toctree-l1"><a class="reference internal" href="5.%E8%8A%82%E7%82%B9%E3%80%81%E7%89%A9%E5%93%81%E5%92%8C%E5%88%B6%E4%BD%9C.html">节点、物品与制作</a>
                    </li>
                </ul>
                <ul>
                    <li class="toctree-l1"><a class="reference internal" href="6.%E5%88%B6%E4%BD%9C%E6%9D%90%E8%B4%A8.html">制作贴图</a>
                    </li>
                </ul>
                <ul>
                    <li class="toctree-l1"><a class="reference internal" href="7.%E8%8A%82%E7%82%B9%E7%BB%98%E5%9B%BE%E7%B1%BB%E5%9E%8B.html">节点绘图类型</a>
                    </li>
                </ul>
                <ul>
                    <li class="toctree-l1"><a class="reference internal" href="8.%E7%89%A9%E5%93%81%E6%A0%8F%E5%92%8C%E8%83%8C%E5%8C%85.html">物品栏和背包</a>
                    </li>
                </ul>
                <ul>
                    <li class="toctree-l1"><a class="reference internal" href="9.%E5%9F%BA%E6%9C%AC%E5%9C%B0%E5%9B%BE%E6%93%8D%E4%BD%9C.html">基本地图操作</a>
                    </li>
                </ul>
      </div>
    </div>
    </nav>

    <section data-toggle="wy-nav-shift" class="wy-nav-content-wrap">

      
      <nav class="wy-nav-top" role="navigation" aria-label="top navigation">
        <i data-toggle="wy-nav-top" class="fa fa-bars"></i>
        <a href="index.html">Minetest Modding Books(中文版)</a>
      </nav>

      
      <div class="wy-nav-content">
        <div class="rst-content">
          <div role="navigation" aria-label="breadcrumbs navigation">
  <ul class="wy-breadcrumbs">
    <li><a href="index.html">Docs</a> &raquo;</li>
    
      
    
    <li>Lua脚本</li>
    <li class="wy-breadcrumbs-aside">
      
    </li>
  </ul>
  
  <hr/>
</div>

          <div role="main">
            <div class="section">
              
                <h1 id="lua">Lua脚本</h1>
<p>在这一章节中，我们将会学习用Lua写脚本，并且复习一些你可能会发现的实用技巧。</p>
<h2 id="_1">代码编辑器</h2>
<p>只需要一个带语法高亮的编辑器就足以使用Lua写脚本。语法高亮根据术语（关键字）类别来显示不同颜色和字体的文字。该功能可以帮助你找到错误。</p>
<pre><code class="language-lua">function ctf.post(team,msg)
    if not ctf.team(team) then
        return false
    end
    if not ctf.team(team).log then
        ctf.team(team).log = {}
    end

    table.insert(ctf.team(team).log,1,msg)
    ctf.save()

    return true
end
</code></pre>
<p>例如，上面代码片段中的关键字将突出显示，例如if、then、end和return。默认情况下，table.insert是Lua附带的函数。<br/>
这里有一些常见的适合Lua的常见编辑器。其他编辑器可以。<br/>
以下是个人推荐的编辑器：
* Windows：<a href="http://atom.io/">Atom</a>，<a href="https://code.visualstudio.com/">VS Code</a>
* Linux：Kate，Gedit，<a href="http://atom.io/">Atom</a>，<a href="https://code.visualstudio.com/">VS Code</a>
* OSX：<a href="http://atom.io/">Atom</a>， <a href="https://code.visualstudio.com/">VS Code</a></p>
<h2 id="lua_1">用Lua写代码</h2>
<h3 id="_2">程序流</h3>
<p>程序是由一行行的命令组成的。我们称这些为“语句”。程序流是这些语句的执行方式。不同类型的流可以让你跳过或跳到命令集。这里有三种类型流：
* 顺序：只需运行一条接一条的语句，不跳过。
* 选择：根据条件跳过序列。
* 迭代（重复）：重复，继续运行相同的语句，直到满足条件为止。</p>
<p>让我们来看看Lua的语句长什么样子：</p>
<pre><code class="language-lua">local a = 2     -- Set 'a' to 2
local b = 2     -- Set 'b' to 2
local result = a + b -- Set 'result' to a + b, which is 4
a = a + 10
print(&quot;Sum is &quot;..result)
</code></pre>
<p>这里发生了什么？
a和b，和result是变量。使用local声明局部变量，并且给他们初始变量。局部将在稍后讨论，因为它是一个非常重要概念的一部分，叫做范围。<br/>
“=”意思是赋值，所以，result = a + b 也就意味着“result”这个变量的值为 a + b。与数学不同的是，变量名可以变得更长（至少一个字母），就像“result”这个变量名一样。另外值得注意的是，Lua是区分大小写的；“A”与“a”是不同的变量。</p>
<h3 id="_3">变量类型</h3>
<p>变量只能是以下类型之一，并且可以在赋值后更改类型。这是一个很好的实践，确保一个变量永远是nil（零）或者是一个单一的非nil（零）类型。<br/></p>
<table>
<thead>
<tr>
<th>Type</th>
<th>Description</th>
<th>Example</th>
</tr>
</thead>
<tbody>
<tr>
<td>Nil（零）</td>
<td>没有初始化，这是个值是空的</td>
<td><code>local A</code>, <code>D = nil</code></td>
</tr>
<tr>
<td>Number（数字）</td>
<td>一个整数或小数</td>
<td><code>local A = 4</code></td>
</tr>
<tr>
<td>String（字符串）</td>
<td>一段文字</td>
<td><code>local D = "one two three"</code></td>
</tr>
<tr>
<td>Boolean（布尔值）</td>
<td>真或假</td>
<td><code>local is_true = false</code>, <code>local E = (1 == 1)</code></td>
</tr>
<tr>
<td>Table（列表）</td>
<td>列表</td>
<td>后面会提到的</td>
</tr>
<tr>
<td>Function（函数）</td>
<td>可执行，可能需要输入几个值（至少一个）或者输出一个值</td>
<td><code>local result = func(1, 2, 3)</code></td>
</tr>
</tbody>
</table>
<h3 id="_4">算术运算符</h3>
<p>这不是一个详尽的清单，不包含所有可能的运算符。<br/></p>
<table>
<thead>
<tr>
<th>符号</th>
<th>意义</th>
<th>例子</th>
</tr>
</thead>
<tbody>
<tr>
<td>A + B</td>
<td>加</td>
<td>2 + 2 = 4</td>
</tr>
<tr>
<td>A - B</td>
<td>减</td>
<td>2 - 10 = -8</td>
</tr>
<tr>
<td>A * B</td>
<td>乘</td>
<td>2 * 2 = 4</td>
</tr>
<tr>
<td>A / B</td>
<td>除</td>
<td>100 / 50 = 2</td>
</tr>
<tr>
<td>A ^ B</td>
<td>平方</td>
<td>2 ^ 2 = 2<sup>2</sup> = 4</td>
</tr>
<tr>
<td>A .. B</td>
<td>拼字符串</td>
<td>"foo" .. "bar" = "foobar"</td>
</tr>
</tbody>
</table>
<h3 id="_5">判断</h3>
<p>最基本的判断就是if语句。它看起来像这样：</p>
<pre><code class="language-lua">local random_number = math.random(1, 100) -- Between 1 and 100.
if random_number &gt; 50 then
    print(&quot;Woohoo!&quot;)
else
    print(&quot;No!&quot;)
end
</code></pre>
<p>这个例子是生成1-100的随机数。如果这个数字大于50，他就会打出“Woohoo!”，否则就会打出“No!”。除了“&gt;”你还能得到什么？</p>
<h3 id="_6">逻辑运算符</h3>
<p>它不包含所有可能的运算符，您可以组合如下运算符：</p>
<table>
<thead>
<tr>
<th>符号</th>
<th>意义</th>
<th>例子</th>
</tr>
</thead>
<tbody>
<tr>
<td>A == B</td>
<td>等于</td>
<td>1 == 1 (true), 1 == 2 (false)</td>
</tr>
<tr>
<td>A ~= B</td>
<td>不等于</td>
<td>1 ~= 1 (false), 1 ~= 2 (true)</td>
</tr>
<tr>
<td>A &gt; B</td>
<td>大于</td>
<td>5 &gt; 2 (true), 1 &gt; 2 (false), 1 &gt; 1 (false)</td>
</tr>
<tr>
<td>A &lt; B</td>
<td>小于</td>
<td>1 &lt; 3 (true), 3 &lt; 1 (false), 1 &lt; 1 (false)</td>
</tr>
<tr>
<td>A &gt;= B</td>
<td>大于等于</td>
<td>5 &gt;= 5 (true), 5 &gt;= 3 (true), 5 &gt;= 6 (false)</td>
</tr>
<tr>
<td>A &lt;= B</td>
<td>小于等于</td>
<td>3 &lt;= 6 (true), 3 &lt;= 3 (true)</td>
</tr>
<tr>
<td>A and B</td>
<td>和（两者都必须要符合）</td>
<td>(2 &gt; 1) and (1 == 1)  (true), (2 &gt; 3) and (1 == 1)  (false)</td>
</tr>
<tr>
<td>A or B</td>
<td>二选一，只要符合一个条件即可</td>
<td>(2 &gt; 1) or (1 == 2) (true), (2 &gt; 4) or (1 == 3) (false)</td>
</tr>
<tr>
<td>not A</td>
<td>相反</td>
<td>not (1 == 2)  (true), not (1 == 1)  (false)</td>
</tr>
</tbody>
</table>
<pre><code class="language-lua">if not A and B then
    print(&quot;Yay!&quot;)
end
</code></pre>
<p>当A和B的值为真为时，就会输出“Yay!”<br/>
逻辑运算符和算术运算符的工作原理完全相同；它们都接受输入并返回一个可以存储的值。</p>
<pre><code class="language-lua">local A = 5
local is_equal = (A == 5)
if is_equal then
    print(&quot;Is equal!&quot;)
end
</code></pre>
<h2 id="_7">编程</h2>
<p>编程是一种处理问题的动作，如对项目列表进行排序，然后将其转换为计算机可以理解的步骤。<br/>
教你编程的逻辑过程超出了本书的范围；但是，以下网站在开发这个过程中非常有用(当然如果你有一定的Lua编程基础，你可以直接看下一部分的内容。当然如果你有其他编程语言的基础，译者本人建议建议也学一下Lua。)：</p>
<ul>
<li><a href="http://www.codecademy.com/">Codecademy</a>是学习“编码”的最佳资源之一，提供了交互式教程体验。</li>
<li><a href="https://scratch.mit.edu/">Scratch</a>是一个很好的资源，当从绝对的基础开始，学习解决问题所需的编程技巧。
    Scratch的目的是教孩子们如何编程，而不是一种严肃的编程语言。</li>
<li><a href="https://www.runoob.com/lua/lua-tutorial.html">菜鸟教程</a>(译者自己补充上去的)：个人极力推荐，提供了大量的在线实例。该网站致力于推广各种编程语言技术，所有资源是完全免费的，并且会根据当前互联网的变化实时更新本站内容。</li>
</ul>
<h2 id="_8">本地和全局范围</h2>
<p>变量是局部变量还是全局变量决定了它可以写入或读取的位置。局部变量只能从定义它的位置访问。举个例子：</p>
<pre><code class="language-lua">-- Accessible from within this script file
local one = 1

function myfunc()
    -- Accessible from within this function
    local two = one + one

    if two == one then
        -- Accessible from within this if statement
        local three = one + two
    end
end
</code></pre>
<p>而全局变量可以从脚本文件中的任何位置访问，也可以从任何其他模组访问。</p>
<pre><code class="language-lua">my_global_variable = &quot;blah&quot;

function one()
    my_global_variable = &quot;three&quot;
end

print(my_global_variable) -- Output: &quot;blah&quot;
one()
print(my_global_variable) -- Output: &quot;three&quot;
</code></pre>
<h3 id="_9"><strong>尽量使用本地变量</strong></h3>
<p>Lua在默认情况下是全局的（与大多数其他编程语言不同）。局部变量必须这样标识。</p>
<pre><code class="language-lua">function one()
    foo = &quot;bar&quot;
end

function two()
    print(dump(foo))  -- Output: &quot;bar&quot;
end

one()
two()
</code></pre>
<p>dump()是一个函数，它可以将任何变量转换为字符串，以便程序员可以看到它是什么。foo变量将被打印为“bar”，包括显示它是字符串的引号。<br/>
这是草率的编码，事实上，Minetest将对此发出警告：</p>
<blockquote>
<p>Assignment to undeclared global 'foo' inside function at init.lua:2</p>
</blockquote>
<p>要更正此问题，请使用“local”：</p>
<pre><code class="language-lua">function one()
    local foo = &quot;bar&quot;
end

function two()
    print(dump(foo))  -- Output: nil
end

one()
two()
</code></pre>
<p>请记住，nil表示<strong>不初始化</strong>。变量尚未赋值、不存在或未初始化（即：设置为零）。<br/>
函数也是如此。函数是一种特殊类型的变量，应该设置为局部的，因为其他模组可以有同名的函数</p>
<pre><code class="language-lua">local function foo(bar)
    return bar * 2
end
</code></pre>
<p>应该使用API表来允许其他mod调用函数，例如：</p>
<pre><code class="language-lua">mymod = {}

function mymod.foo(bar)
    return &quot;foo&quot; .. bar
end

-- In another mod, or script:
mymod.foo(&quot;foobar&quot;)
</code></pre>
<h2 id="lua_2">包含其他Lua脚本</h2>
<p>如果要在模组中包含其他Lua脚本，推荐使用dofile。</p>
<pre><code class="language-lua">dofile(minetest.get_modpath(&quot;modname&quot;) .. &quot;/script.lua&quot;)
</code></pre>
<p>在脚本文件的任何函数之外声明的“local”变量将是该脚本的本地变量。脚本可以返回一个值，该值对于共享私有局部变量非常有用：</p>
<pre><code class="language-lua">-- script.lua
return &quot;Hello world!&quot;

-- init.lua
local ret = dofile(minetest.get_modpath(&quot;modname&quot;) .. &quot;/script.lua&quot;)
print(ret) -- Hello world!
</code></pre>
<p>后面的章节将详细讨论如何分割mod的代码。不过，目前最简单的方法是为不同类型的事物（nodes.lua、crafts.lua、craftitems.lua等）创建不同的文件。</p>
              
            </div>
          </div>
          <footer>
  
    <div class="rst-footer-buttons" role="navigation" aria-label="footer navigation">
      
        <a href="5.%E8%8A%82%E7%82%B9%E3%80%81%E7%89%A9%E5%93%81%E5%92%8C%E5%88%B6%E4%BD%9C.html" class="btn btn-neutral float-right" title="节点、物品与制作">Next <span class="icon icon-circle-arrow-right"></span></a>
      
      
        <a href="3.%E5%85%A5%E9%97%A8.html" class="btn btn-neutral" title="入门"><span class="icon icon-circle-arrow-left"></span> Previous</a>
      
    </div>
  

  <hr/>

  <div role="contentinfo">
    <!-- Copyright etc -->
    
  </div>

  Built with <a href="https://www.mkdocs.org/">MkDocs</a> using a <a href="https://github.com/snide/sphinx_rtd_theme">theme</a> provided by <a href="https://readthedocs.org">Read the Docs</a>.
</footer>
      
        </div>
      </div>

    </section>

  </div>

  <div class="rst-versions" role="note" aria-label="versions">
  <span class="rst-current-version" data-toggle="rst-current-version">
    
    
      <span><a href="3.%E5%85%A5%E9%97%A8.html" style="color: #fcfcfc">&laquo; Previous</a></span>
    
    
      <span><a href="5.%E8%8A%82%E7%82%B9%E3%80%81%E7%89%A9%E5%93%81%E5%92%8C%E5%88%B6%E4%BD%9C.html" style="color: #fcfcfc">Next &raquo;</a></span>
    
  </span>
</div>
    <script>var base_url = '.';</script>
    <script src="js/theme_extra.js" defer></script>
    <script src="js/theme.js" defer></script>
      <script src="search/main.js" defer></script>
    <script defer>
        window.onload = function () {
            SphinxRtdTheme.Navigation.enable(true);
        };
    </script>

</body>
</html>
